package de.pyranja.money.core;

import static com.google.common.base.Preconditions.checkNotNull;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Currency;

import de.pyranja.money.MoneyCalculator;
import de.pyranja.money.exception.CurrencyMismatchException;

/**
 * Executes calculations on {@link de.pyranja.money.core.BaseMoney BaseMoney} 
 * objects. You may specify a {@link java.math.MathContext MathContext} to use 
 * on calculations.
 * 
 * @author Chris Borckholder
 */
public class BasicMoneyCalculator implements MoneyCalculator {

	private final MathContext mc;
	
	/**
	 * Builds with a standard MathContext (IEEE 754R)
	 */
	public BasicMoneyCalculator() {
		this.mc = MathContext.DECIMAL32;
	}
	
	/**
	 * Builds with custom MathContext
	 */
	public BasicMoneyCalculator(MathContext mc) {
		this.mc = checkNotNull(mc,"Invalid MathContext");
	}
	
	@Override
	public BaseMoney add(final BaseMoney a, final BaseMoney b) {
		final Currency currency = matchCurrencies(checkNotNull(a),checkNotNull(b));
		final BigDecimal result = a.getAmount().add(b.getAmount(), mc);
		return new BaseMoney(result,currency);
	}

	@Override
	public BaseMoney subtract(final BaseMoney a, final BaseMoney b) {
		final Currency currency = matchCurrencies(checkNotNull(a),checkNotNull(b));
		final BigDecimal result = a.getAmount().subtract(b.getAmount(), mc);
		return new BaseMoney(result,currency);
	}
	
	@Override
	public BaseMoney multiply(final BaseMoney a, final BigDecimal b) {
		final Currency currency = matchCurrencies(a);
		final BigDecimal result = a.getAmount().multiply(b);
		return new BaseMoney(result,currency);
	}
	
	private Currency matchCurrencies(final BaseMoney... inputs) {
		Currency currency = null;
		for (BaseMoney input : inputs) {
			if (currency == null) {
				currency = input.getCurrency();
			} else {
				if (!currency.equals(input.getCurrency())) {
					throw new CurrencyMismatchException(
							"Cannot calculate on money in different currencies",
							inputs);
				}
			}
		}
		return currency;
	}
}
